package net.muchine.test.ddd;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Component;

@Component
public class EntryPointRegistrar implements Registrar {
	private Map<Class<?>, Map<String, EntryPoint>> registry;
	
	public EntryPointRegistrar() {
		this.init();
	}
	
	public void init() {
		this.registry = new HashMap<Class<?>, Map<String, EntryPoint>>();
	}
	
	public void add(Class<?> entryPointClass, EntryPoint entryPoint) {
		this.addObject(entryPointClass, entryPoint);
	}
	
	public EntryPoint get(Class<?> entryPointClass, String objectName) {
		return this.getObject(entryPointClass, objectName);
	}
	
	public EntryPoint delete(Class<?> entryPointClass, String objectName) {
		return this.deleteObject(entryPointClass, objectName);
	}
	
	public Collection<? extends EntryPoint> getAll(Class<? extends EntryPoint> entryPointClass) {
		return this.getAllObjects(entryPointClass);
	}

	private void addObject(Class<?> entryPointClass, EntryPoint entryPoint) {
		Map<String, EntryPoint> entryPoints = registry.get(entryPointClass);
		
		if (entryPoints == null) {
			entryPoints = new HashMap<String, EntryPoint>();
			registry.put(entryPointClass, entryPoints);
		}
		
		entryPoints.put(entryPoint.getIdentity(), entryPoint);
	}

	private EntryPoint getObject(Class<?> entryPointClass, String objectName) {
		Map<String, EntryPoint> entryPoints = registry.get(entryPointClass);
		return entryPoints.get(objectName);
	}
	
	private EntryPoint deleteObject(Class<?> entryPointClass, String objectName) {
		Map<String, EntryPoint> entryPoints = registry.get(entryPointClass);
		return entryPoints.remove(objectName);
	}

	@SuppressWarnings("unchecked")
	private Collection<? extends EntryPoint> getAllObjects(
			Class<?> entryPointClass) {
		Map<String, EntryPoint> foundEntryPoints = registry.get(entryPointClass);
		
		return (Collection<? extends EntryPoint>) Collections.unmodifiableCollection(foundEntryPoints != null ?
				registry.get(entryPointClass).values() : 
				Collections.EMPTY_SET);
	}
}
